package aladyn;

import java.lang.reflect.InvocationTargetException;

import java.lang.reflect.Method;
import java.util.StringTokenizer;

import aladyn.id.Identificater;
import aladyn.testclass.*;

/**
 * 
 * @author YiHan WANG, Qi XU, Bo CAI
 *
 */
public class TestMain {

	/**
	 * @param args
	 * @throws NoSuchMethodException 
	 * @throws SecurityException 
	 * @throws InvocationTargetException 
	 * @throws IllegalAccessException 
	 * @throws IllegalArgumentException 
	 */
	public static void main(String[] args) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
		
		String str1, str2;
		
		// Point
		System.out.println("Point");
		Point pt = new Point();
		str1 = invokeSerialize(pt);
		str2 = invokeSerialize(pt);
		invokeDeserialize1(pt, str1);
		invokeDeserialize2(pt, str2);

		Point pt2 = new Point(1, 2);
		str1 = invokeSerialize(pt2);
		str2 = invokeSerialize(pt2);
		invokeDeserialize1(pt2, str1);
		invokeDeserialize2(pt2, str2);
		
		// PointColor
		System.out.println("\nPointColor");
		PointColor ptc = new PointColor();
		str1 = invokeSerialize(ptc);
		str2 = invokeSerialize(ptc);
		invokeDeserialize1(ptc, str1);
		invokeDeserialize2(ptc, str2);
		
		PointColor ptc2 = new PointColor(3, 4, 'r');
		str1 = invokeSerialize(ptc2);
		str2 = invokeSerialize(ptc2);
		invokeDeserialize1(ptc2, str1);
		invokeDeserialize2(ptc2, str2);
		
		// Dot
		System.out.println("\nDot");
		Dot dot = new Dot(3, 4, "123");
		dot.y = new int[2][3];
		dot.y[0][0] = 51;
		dot.y[0][1] = 41;
		dot.y[0][2] = 31;
		dot.y[1][0] = 21;
		dot.y[1][1] = 11;
		dot.y[1][2] = 01;
		Point[][][] ptab = new Point[2][2][2];
		ptab[0][0][0] = new Point();
		ptab[0][0][1] = new Point();
		ptab[0][1][0] = new Point(11, 12);
		ptab[1][0][0] = new PointColor();
		ptab[1][0][1] = new PointColor();
		ptab[1][1][0] = new PointColor(11, 12, 'c');
		dot.pts = ptab;
		str1 = invokeSerialize(dot);
		str2 = invokeSerialize(dot);
		Dot d1 = (Dot) invokeDeserialize1(dot, str1);
		Dot d2 = (Dot) invokeDeserialize2(dot, str2);
		// juste pour enlever les warnings
		d1 = d2;
		d2 = d1;
		
		// palier 5, test cycle
//		Je ne comprend pas pourquoi cette partie me fait cet erreur, je n'ai pas réussi à débugué
		
//		Exception in thread "main" java.lang.VerifyError: (class: aladyn/testclass/A, method: deserialize signature: (Ljava/lang/String;Ljava/util/StringTokenizer;)Ljava/lang/Object;) Bad type in putfield/putstatic
//		at aladyn.TestMain.main(TestMain.java:85)
		/*
		System.out.println("\nCycle");
		A a = new A(11111);
		B b = new B(22222);
		a.b = b;
		b.a = a;
		str1 = invokeSerialize(a);
		invokeDeserialize1(a, str1);
		str1 = invokeSerialize(b);
		invokeDeserialize1(b, str1);
		*/

		System.out.println();
		Identificater.print();
	}
	
	public static String invokeSerialize(Object o) 
	throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException{
		Class<?> c = o.getClass();
		Method m = c.getDeclaredMethod("serialize");
		String res = (String) m.invoke(o);
		System.out.println("serialize \t: " + o + " \t\t-> " + res);
		return res;
	}
	
	public static Object invokeDeserialize1(Object o, String serialized) 
	throws SecurityException, NoSuchMethodException, IllegalArgumentException, 
			IllegalAccessException, InvocationTargetException{
		Class<?> c = o.getClass();
		Method m1 = c.getDeclaredMethod("deserialize", String.class);
		
		Object res1 = (Object) m1.invoke(o, serialized);
		System.out.println("deserialize1 \t: " + serialized + " \t\t\t\t-> " + res1);
		return res1;
	}
	
	public static Object invokeDeserialize2(Object o, String serialized) 
	throws SecurityException, NoSuchMethodException, IllegalArgumentException, 
			IllegalAccessException, InvocationTargetException{
		Class<?> c = o.getClass();
		StringTokenizer t = new StringTokenizer(serialized, "@");
		String type = t.nextToken();
		Method m2 = c.getDeclaredMethod("deserialize", String.class, StringTokenizer.class);
		Object res2 = (Object) m2.invoke(o, type, t);
		System.out.println("deserialize2 \t: " + serialized + " \t\t\t\t\t-> " + res2);
		return res2;
	}

}
